<template>
  <div class="wrapper-add-edit">
    <el-form ref="refForm" :model="formData" :rules="rules" label-width="120px">
      <el-form-item label="角色名称" prop="label">
        <el-col :span="10">
          <el-input ref="refLabel" v-model="formData.label" maxlength="20" show-word-limit />
        </el-col>
        <el-col :span="13" :push="1">
          <span>例：“微信公众号管理员”</span>
        </el-col>
      </el-form-item>

      <el-form-item label="角色代码" prop="code">
        <el-col :span="10">
          <el-input ref="refCode" v-model="formData.code" maxlength="20" show-word-limit disabled>
            <template #prepend>ROLE_</template>
          </el-input>
        </el-col>
        <el-col :span="13" :push="1">
          <span>填写代码英文，自动在开头添加“ROLE_”并转换为大写</span>
        </el-col>
      </el-form-item>

      <el-form-item label="简介" prop="intro">
        <el-col :span="14">
          <el-input
            v-model="formData.intro"
            :autosize="{ minRows: 5, maxRows: 8 }"
            maxlength="200"
            show-word-limit
            type="textarea"
            placeholder="角色描述"
          />
        </el-col>
      </el-form-item>

      <el-form-item label="管理权限">
        <el-col>
          <div v-for="(item, index) in allPurviewList" :key="item" class="wrapper-checkbox">
            <!--子权限全选框-->
            <el-checkbox
              v-model="checkedAllList[index]"
              :indeterminate="indeterminateList[index]"
              :label="tagList[index]"
              @change="onCheckAllChanged($event, index)"
            />
            <!--子权限复选框组-->
            <el-checkbox-group v-model="checkedPurviewList[index]" @change="onCBChanged(index)">
              <el-checkbox v-for="subItem in item.PurviewList" :key="subItem.id" :label="subItem.id">
                {{ subItem.name }}
              </el-checkbox>
            </el-checkbox-group>
          </div>
        </el-col>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" @click="onUpdate">确定修改</el-button>
        <el-button @click="onBack2List">取消并返回</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
import { toastSuccess, toastError } from '@/utils/toast'
import { getSStorageObj } from '@/utils/web-storage'

import router from '@/router'
import store from '@/store'
import { defineComponent, ref, onMounted } from 'vue'
export default defineComponent({
  name: 'RoleEditView',
  setup() {
    const formData = ref({
      id: 0,
      label: '',
      code: '',
      intro: '',
      dtCreate: new Date().getTime(),
      flagEnabled: true,
      flagSystem: false,
    })
    // 此变量存放api返回的所有权限列表数据
    const allPurviewList = ref({
      Keyword: '',
      PurviewList: [],
    })
    // 全选框数组
    const checkedAllList = ref([])
    // 全选框中间状态数组
    const indeterminateList = ref([])
    // 全选框的名称数组
    const tagList = ref([])
    // 所有选中的权限，注意是二维数组，每个子元素也是数组，每个子元素存放选中的子权限的id值
    const checkedPurviewList = ref([])
    const refForm = ref(null)
    const refLabel = ref(null)
    const refCode = ref(null)
    const rules = ref({
      label: [{ required: true, message: '请输入角色名称', trigger: 'blur' }],
      code: [{ required: true, message: '请输入角色代码', trigger: 'blur' }],
    })
    // 得到的某个关键字下所有权限列表
    const listAllPurview = () => {
      return store
        .dispatch('sys_purview/listAllByKeyword')
        .then((response) => {
          return response
        })
        .catch((error) => {
          console.log('得到的某个关键字下所有权限列表时出现错误：', error)
        })
    }
    // 点击某全选框事件，注意调用方法时加括号和不加括号的区别
    // https://blog.csdn.net/weixin_56008510/article/details/121948791
    const onCheckAllChanged = (flagChecked, index) => {
      // console.log('flag', flagChecked)
      checkedPurviewList.value[index] = []
      if (flagChecked) {
        for (const purview of allPurviewList.value[index].PurviewList) {
          checkedPurviewList.value[index].push(purview.id)
        }
      }
      indeterminateList.value[index] = false
    }
    // 点击某复选框事件
    // 调用时如果不加括号，则传入的默认参数 val 是选中值的数组
    // 调用时如果加括号，则传入自定义参数，但是可以用$event表示默认参数
    const onCBChanged = (index) => {
      console.log('checkedPurviewList', checkedPurviewList.value[index])
      // 得到当前选中权限的个数
      const checkedCount = checkedPurviewList.value[index].length
      // 得到当前子权限组
      const purviewList = allPurviewList.value[index].PurviewList
      // 设置全选框的状态，当选中的权限个数等于子权限组的总长度时
      checkedAllList.value[index] = checkedCount === purviewList.length
      // 设置全选框的中间状态
      indeterminateList.value[index] = checkedCount > 0 && checkedCount < purviewList.length
    }
    // 点击更新确认按钮
    const onUpdate = async () => {
      const checkedPurviewIds = []
      for (const checkedPurview of checkedPurviewList.value) {
        for (const id of checkedPurview) {
          checkedPurviewIds.push(id)
        }
      }
      if (checkedPurviewIds.length === 0) {
        toastError('请选择角色所属权限！', 5)
        return false
      }
      refForm.value.validate((valid) => {
        if (!valid) {
          toastError('验证失败，请检查输入的信息！', 5)
          return
        }
        // 提交后台
        formData.value.code = 'ROLE_' + formData.value.code.toUpperCase()
        store
          .dispatch('sys_role/modifyAll', {
            SysRole: formData.value,
            PurviewIds: checkedPurviewIds,
          })
          .then(() => {
            toastSuccess('更新角色成功！')
            router.push({ path: 'list-all' })
          })
          .catch((error) => {
            toastError('服务器修改角色返回错误：')
            console.log('服务器添加角色返回错误：', error)
          })
      })
    }
    // 取消并返回列表页
    const onBack2List = () => {
      router.push({ path: 'list-all' })
    }
    // 得到传过来的 role 的详细资料，但是没有得到此角色拥有的权限
    const getQuery = () => {
      const role = getSStorageObj('ParamData')
      if (!role) onBack2List()
      console.log('getQuery:', role)
      formData.value.id = role.id
      formData.value.label = role.label
      formData.value.code = role.code.substring(5)
      formData.value.intro = role.intro
      formData.value.dtCreate = role.dtCreate
      formData.value.flagEnabled = role.flagEnabled
      formData.value.flagSystem = role.flagSystem
    }
    // 根据角色id得到此角色下所有权限id数组
    const getPurviewIds = (idRole) => {
      return store
        .dispatch('sys_role_purview/getPurviewIdsByIdRole', idRole)
        .then((response) => {
          return response
        })
        .catch((error) => {
          console.log('根据角色id得到所有的权限id列表出现错误：', error)
        })
    }
    // 设置选中的权限复选框状态
    const setCheckedPurviewList = (purviewIds) => {
      // 定义一个数组存放某大类下小类选中的权限id
      let checkedIdList = []
      // 循环所有的权限组，设置已选中子权限数组，从而设置复选框选中状态
      for (const i in allPurviewList.value) {
        checkedIdList = []
        // 循环该角色下所有的权限
        for (const purview of allPurviewList.value[i].PurviewList) {
          // 循环遍历已有的权限数组，如果相等则加到已选权限数组里
          for (const j in purviewIds) {
            if (purview.id === purviewIds[j] + '') {
              checkedIdList.push(purview.id)
            }
          }
        }
        checkedPurviewList.value.push(checkedIdList)
      }
      // 经过上面的循环，listCheckedPurviewId存了某个权限组下的已选中的权限id
      // console.log('checkedPurviewList：', checkedPurviewList.value)
      // 设置全选框用到的变量
      let totalChecked = 0
      let checkedCount = 0
      // 循环所有的权限组，设置全选框状态
      for (const i in allPurviewList.value) {
        // 某大类下子权限的总数量
        totalChecked = allPurviewList.value[i].PurviewList.length
        // 某大类下小类选中的总数
        checkedCount = checkedPurviewList.value[i].length
        // 设置全选框的状态，当选中的权限个数等于子权限组的总长度时
        checkedAllList.value[i] = checkedCount === totalChecked
        // 设置全选框的中间状态
        indeterminateList.value[i] = checkedCount > 0 && checkedCount < totalChecked
      }
    }

    const init = async () => {
      // 得到roleid
      getQuery()
      // 得到所有权限列表
      allPurviewList.value = await listAllPurview()
      // 初始化复选框相关变量
      for (const index in allPurviewList.value) {
        indeterminateList.value.push(false)
        checkedAllList.value.push(false)
        tagList.value.push(allPurviewList.value[index].Keyword)
      }
      // 根据roleid得到该角色所有权限
      const purviewIds = await getPurviewIds(formData.value.id)
      // 根据roleid和所有权限列表做比对，设置复选框组
      setCheckedPurviewList(purviewIds)
    }

    onMounted(() => {
      init()
    })

    return {
      formData,
      rules,
      allPurviewList,
      checkedAllList,
      indeterminateList,
      tagList,
      checkedPurviewList,
      refForm,
      refLabel,
      refCode,
      init,
      getQuery,
      listAllPurview,
      getPurviewIds,
      setCheckedPurviewList,
      onCheckAllChanged,
      onCBChanged,
      onUpdate,
      onBack2List,
    }
  },
})
</script>

<style lang="scss" scoped>
.wrapper-checkbox {
  border: 1px solid #d4d4d4;
  padding: 16px;
  margin-bottom: 16px;
}
</style>
